<template>
  <el-descriptions ref="detailRef" :model="modelValue">
    <!-- 动态生成详情项 -->
    <el-descriptions-item v-for="item in detailItems" :key="item.prop" :label="item.label" v-bind="getItemProps(item)">
      <template #label>
        <div class="fixed-width-label">
          <el-tooltip content-trigger="hover" :content="item.label" placement="top">
            <template #content>
              <div class="tooltip-content">{{ item.label }}</div>
            </template>
            <span class="ellipsis-label">{{ item.label }}</span>
          </el-tooltip>
        </div>
      </template>
      <template #default>
        <div class="fixed-width-content">
          <!-- 自定义内容插槽 -->
          <slot :name="item.prop" :value="modelValue[item.prop]" :row="modelValue">
            <!-- 动态渲染详情内容（图片类型单独处理） -->
            <template v-if="item.type === 'text' || !item.type">
              <span>
                {{ getFomatterValue(modelValue[item.prop], item.formatter) }}
              </span>
            </template>
            <template v-else-if="item.type === 'image'">
              <!-- 图片数组处理 -->
              <div v-if="isImageArray(getFomatterValue(modelValue[item.prop], item.formatter))">
                <el-image
                  v-for="(img, imgIndex) in formatImageArray(getFomatterValue(modelValue[item.prop], item.formatter))"
                  :key="imgIndex"
                  :src="img"
                  :zoom-rate="1.2"
                  :max-scale="7"
                  :min-scale="0.2"
                  show-progress
                  fit="cover"
                  class="detail-image"
                  @click="
                    openImageViewer(imgIndex, formatImageArray(getFomatterValue(modelValue[item.prop], item.formatter)))
                  "
                  :preview-src-list="[img]"
                />
              </div>
              <!-- 单个图片URL处理 -->
              <div v-else-if="isImageUrl(getFomatterValue(modelValue[item.prop], item.formatter))">
                <el-image
                  :src="getFomatterValue(modelValue[item.prop], item.formatter)"
                  :zoom-rate="1.2"
                  :max-scale="7"
                  :min-scale="0.2"
                  show-progress
                  fit="cover"
                  class="detail-image"
                  @click="openImageViewer(0, [getFomatterValue(modelValue[item.prop], item.formatter)])"
                  :preview-src-list="[getFomatterValue(modelValue[item.prop], item.formatter)]"
                />
              </div>
              <span v-else-if="item.default">
                {{ item.default }}
              </span>
            </template>
            <!-- 非图片类型：沿用原有组件渲染逻辑 -->
            <template v-else>
              <component
                :is="getDetailComponent(item)"
                :value="modelValue[item.prop]"
                :row="modelValue"
                v-bind="getComponentProps(item)"
              />
            </template>
          </slot>
        </div>
      </template>
    </el-descriptions-item>

    <!-- 操作按钮插槽 -->
    <template #extra>
      <slot name="actions"></slot>
    </template>
    <!-- 图片预览器（全局唯一，默认隐藏） -->
    <el-image-viewer
      v-if="showImageViewer"
      :url-list="imageViewerList"
      show-progress
      :initial-index="imageViewerIndex"
      @close="closeImageViewer"
    />
  </el-descriptions>
</template>

<script setup>
import { ElDescriptions, ElDescriptionsItem, ElImage, ElImageViewer } from 'element-plus'
import { ref } from 'vue'
import { useTemplateRef } from 'vue'

// 1. 定义Props（新增图片相关配置项）
const props = defineProps([
  'detailItems',
  'title',
  // 新增：图片相关配置（可选，父组件可覆盖）
  'closeOnClickModal' // 图片预览器点击遮罩关闭，默认true
])

const modelValue = defineModel()

// 2. 组件实例与图片预览状态
const detailRef = useTemplateRef('detailRef')
// 图片预览器状态
const showImageViewer = ref(false) // 预览器显隐
const imageViewerList = ref([]) // 预览图片列表
const imageViewerIndex = ref(0) // 预览初始索引
const getFomatterValue = (val, fun) => {
  if (!fun) {
    return val
  }
  return fun(val)
}
// 3. 原有：详情内容组件映射（保留，非图片类型沿用）
const detailComponentMap = {
  text: {
    render: value => value ?? '-'
  },
  array: {
    render: value => (Array.isArray(value) ? value.join('，') : '-')
  },
  formatter: {
    render: (value, props, item) => item.formatter?.(value, props.row) ?? '-'
  }
}

// 4. 新增：图片处理核心方法
/**
 * 判断是否为图片数组（支持 [{src: 'xxx'}] 或 ['xxx', 'xxx'] 格式）
 */
const isImageArray = value => {
  if (!Array.isArray(value)) return false
  // 数组元素为对象时，必须包含src字段；为字符串时必须是URL
  return value.every(
    item =>
      (typeof item === 'object' && item.src && isImageUrl(item.src)) || (typeof item === 'string' && isImageUrl(item))
  )
}

/**
 * 判断是否为有效图片URL（http/https开头，包含图片后缀）
 */
const isImageUrl = value => {
  if (typeof value !== 'string') return false
  const imageReg = /^(http|https):\/\/.+\.(jpg|jpeg|png|gif|bmp|svg|webp)$/i
  return imageReg.test(value)
}

/**
 * 格式化图片数组（统一转为 ['url1', 'url2'] 格式）
 */
const formatImageArray = value => {
  if (!isImageArray(value)) return []
  return value.map(item => (typeof item === 'object' ? item.src : item))
}

/**
 * 打开图片预览器
 */
const openImageViewer = (index, urlList) => {
  imageViewerList.value = urlList
  imageViewerIndex.value = index
  showImageViewer.value = true
}

/**
 * 关闭图片预览器
 */
const closeImageViewer = () => {
  showImageViewer.value = false
  imageViewerList.value = []
  imageViewerIndex.value = 0
}

// 5. 原有：工具方法（保留，无修改）
const rootItemProps = ['label', 'prop', 'type', 'formatter', 'span', 'componentProps', 'default']
function omit(obj, keys) {
  const result = { ...obj }
  ;(Array.isArray(keys) ? keys : [keys]).forEach(key => delete result[key])
  return result
}

function getItemProps(item) {
  const baseProps = { span: item.span || 1 }
  const extraProps = omit(item, rootItemProps)
  return { ...baseProps, ...extraProps }
}

function getDetailComponent(item) {
  if (item.component) return item.component
  const itemType = item.formatter ? 'formatter' : item.type || 'text'
  const componentConfig = detailComponentMap[itemType]
  if (componentConfig?.render) {
    return {
      setup(props) {
        return () => componentConfig.render(props.value, props, item)
      }
    }
  }
  return componentConfig?.component || (() => props.value ?? '-')
}

function getComponentProps(item) {
  const value = modelValue[item.prop]
  const itemType = item.formatter ? 'formatter' : item.type || 'text'
  const componentConfig = detailComponentMap[itemType]
  const defaultCompProps = componentConfig?.props?.(item, value) || {}
  const userCompProps = item.componentProps || {}
  return { ...defaultCompProps, ...userCompProps, value, row: modelValue }
}

// 6. 暴露方法（新增图片预览控制方法）
defineExpose({
  getDetailInstance: () => detailRef.value,
  refresh: () => detailRef.value?.updateProps({ modelValue: modelValue.value }),
  openImageViewer, // 暴露预览方法（父组件可调用）
  closeImageViewer // 暴露关闭方法
})
</script>

<style scoped>
/* 标签固定宽度样式 */
.fixed-width-label {
  width: 120px; /* 设置标签固定宽度 */
}

.ellipsis-label {
  display: inline-block;
  max-width: 100%;
}

.tooltip-content {
  max-width: 300px;
  white-space: normal;
  word-break: break-all;
}

/* 内容区域固定宽度样式 */
.fixed-width-content {
  width: 200px; /* 设置内容区域固定宽度 */
}
/* 原有样式保留，新增图片相关样式 */
.detail-image {
  width: 50px; /* 支持父组件自定义宽度 */
  height: 50px; /* 支持父组件自定义高度 */
  border-radius: 4px;
  cursor: zoom-in;
  margin-right: 8px; /* 图片间距 */
  margin-bottom: 8px; /* 多行图片换行间距 */
  display: inline-block;
}

/* 图片容器样式 */
.image-container {
  line-height: 1; /* 消除行高影响 */
}

/* 图片空值兜底样式 */
.image-placeholder {
  color: #909399;
  line-height: 50px; /* 与图片高度对齐 */
}
</style>